package org.epanetgrid.otimizacao.evaluators;

import java.util.List;

import org.epanetgrid.otimizacao.ag.SPFitness;
import org.epanetgrid.otimizacao.searchspace.IndividualEvaluator;
import org.epanetgrid.otimizacao.simulation.GradienteNaoConvergeOtimizacaoException;
import org.epanetgrid.otimizacao.simulation.SimulacaoNaoConvergeException;
import org.jheuristics.Individual;
import org.jheuristics.ga.FitnessEvaluator;
import org.jheuristics.ga.GAConfig;
import org.jheuristics.ga.GAStatus;
import org.jheuristics.ga.Population;


/**
 * Avalia um indiv�duo retornando um SPFitness.
 *
 * @author Marcell Manfrin, marcell@ourgrid.org, Sep 13, 2005
 */
public class SimpleGAIndividualFitnessEvaluator implements FitnessEvaluator {
	private IndividualEvaluator evaluator;
	private int indexCusto;
	private int indexPontoDeFalha;
	private int indexSeveridade;
	private int indexTipoMutacao;

	/**
	 * 
	 * @param custo Index do custo no dataApplication dos indiv�duos
	 * @param falha Index da falha no dataApplication dos indiv�duos
	 * @param severidade Index da severidade no dataApplication dos indiv�duos
	 * @param tipoDeMutacao Index do tipo de muta��o no dataApplication dos indiv�duos
	 */
	public SimpleGAIndividualFitnessEvaluator(int custo, int falha, int severidade, int tipoDeMutacao) {
		this(null, custo, falha, severidade, tipoDeMutacao);
	}

	/**
	 * 
	 * @param evaluator respons�vel por setar o dataApplication no indiv�duo
	 * @param custo Index do custo no dataApplication dos indiv�duos
	 * @param falha Index da falha no dataApplication dos indiv�duos
	 * @param severidade Index da severidade no dataApplication dos indiv�duos
	 * @param tipoDeMutacao Index do tipo de muta��o no dataApplication dos indiv�duos
	 */
	public SimpleGAIndividualFitnessEvaluator(IndividualEvaluator evaluator, int custo, int falha, int severidade, int tipoDeMutacao) {
		this.evaluator = evaluator;
		indexCusto = custo;
		indexPontoDeFalha = falha;
		indexSeveridade = severidade;
		indexTipoMutacao = tipoDeMutacao;
	}

	/*
	 * (non-Javadoc)
	 * @see org.jheuristics.ga.FitnessEvaluator#evaluateFitness(org.jheuristics.Individual, org.jheuristics.ga.Population, org.jheuristics.ga.GAStatus, org.jheuristics.ga.GAConfig)
	 */
	public Comparable evaluateFitness(Individual individual, Population population, GAStatus status, GAConfig config) throws GradienteNaoConvergeOtimizacaoException {
		if (null != evaluator) {
			evaluator.evaluate(individual);
		}
		if(individual.getDataApplication() == null) {
			throw new SimulacaoNaoConvergeException("");
		}
//		System.out.println("INdividuo: "+OtimizacaoUtils.gensToString((List<BitString>) individual.getGens()));
//		System.out.println("Data: "+individual.getDataApplication());
//		System.out.println("Fit>: "+individual.getFitness());
		List values = (List) individual.getDataApplication();
		if (((Long) values.get(indexPontoDeFalha)).intValue() == -1) {
			Comparable fitness = new SPFitness(((Number) values.get(indexCusto)).doubleValue());
			return fitness;
		}
		Comparable fitness = new SPFitness(((Number) values.get(indexCusto)).doubleValue(), ((Number) values.get(indexPontoDeFalha)).intValue(), ((Number) values.get(indexSeveridade)).intValue(), ((Number) values.get(indexTipoMutacao)).intValue());
		return fitness;
	}

}
